﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Zhy.DigitaPlatform.Common.Base;
using Zhy.DigitaPlatform.Entities;
using Zhy.DigitaPlatform.IDataAccess;
using Zhy.DigitaPlatform.Models;

namespace Zhy.DigitaPlatform.ViewModels
{
    /// <summary>
    /// 配置业务类
    /// </summary>
    public class ConfigViewModel : ViewModelBase
    {
        /// <summary>
        /// 编辑区域的动态组件集合
        /// </summary>
        public ObservableCollection<DeviceItemModel> DeviceList { get; set; } = new ObservableCollection<DeviceItemModel>();
        /// <summary>
        /// 属性选项下拉列表集合
        /// </summary>
        public List<PropOptionModel> PropOptions { get; set; }
        /// <summary>
        /// 当前选择设备信息
        /// </summary>
        private DeviceItemModel currentDevice;
        /// <summary>
        /// 当前选中的组件
        /// </summary>
        public DeviceItemModel CurrentDevice
        {
            get => currentDevice;
            set => Set(ref currentDevice, value);
        }

        private string _saveFailedMessage;

        public string SaveFailedMessage
        {
            get { return _saveFailedMessage; }
            set { Set(ref _saveFailedMessage, value); }
        }
        /// <summary>
        /// 组件数据集合
        /// </summary>
        public List<ThumbModel> ThumbList { get; set; }
        /// <summary>
        /// 编辑区域组件放下触发的命令
        /// </summary>
        public RelayCommand<object> ItemDropCommand { get; set; }
        public RelayCommand<object> KeyDownCommand { get; set; }
        /// <summary>
        /// 保存按钮命令
        /// </summary>
        public RelayCommand<object> SaveCommand { get; set; }
        /// <summary>
        /// 关闭失败提示信息面板命令
        /// </summary>
        public RelayCommand<object> CloseSaveFailedCommand { get; set; }
        /// <summary>
        /// 组件选中命令
        /// </summary>
        public RelayCommand<DeviceItemModel> DeviceSelectedCommand { get; set; }
        /// <summary>
        /// 只要页面有一次保存成功，页面关闭时就出发主页面刷新方法
        /// </summary>
        private bool _windowState = false;
        /// <summary>
        /// 页面关闭命令
        /// </summary>
        public RelayCommand<object> CloseCommand { get; set; }

        /// <summary>
        /// 数据库操作类
        /// </summary>
        ILocalDataAccess _localDataAccess;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="localDataAccess">注入数据库操作对象</param>
        public ConfigViewModel(ILocalDataAccess localDataAccess)
        {
            _localDataAccess = localDataAccess;
            // 设计模式加载下面的数据会比较卡 - 在运行模式下加载下面的数据
            if (!IsInDesignMode)
            {
                // 实例化组件集合
                ThumbList = new List<ThumbModel>();
                #region 通过数据库维护组件数据初始化-建议使用配置文件方式维护
                // 通过数据库维护
                var ts = localDataAccess.GetThumbList();
                ThumbList = ts.GroupBy(t => t.Category).Select(g => new ThumbModel
                {
                    Header = g.Key,
                    Children = g.Select(b => new ThumbItemModel
                    {
                        Icon = "pack://application:,,,/Zhy.DigitaPlatform.Assets;component/Images/Thumbs/" + b.Icon,
                        Header = b.Header,
                        TargetType = b.TargetType,
                        Width = b.Width,
                        Height = b.Height
                    }).ToList()
                }).ToList();
                #endregion

                #region 组件数据初始化 - 临时维护方式
                #region 设备数据
                // 通过数据库维护
                //ThumbModel model = new ThumbModel()
                //{
                //    Header = "设备",
                //    Children = new List<ThumbItemModel>() {
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //}
                //};
                //ThumbList.Add(model);
                #endregion

                #region 数字仪表数据
                //model = new ThumbModel()
                //{
                //    Header = "数字仪表",
                //    Children = new List<ThumbItemModel>() {
                //    new ThumbItemModel(){
                //        TargetType="AirCompressor",
                //        Width=120,Height=90 },
                //    new ThumbItemModel(){
                //        TargetType="Hello",
                //        Width=10,Height=200
                //    },
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //}
                //};
                //ThumbList.Add(model);
                #endregion

                #region 管道数据
                //model = new ThumbModel()
                //{
                //    Header = "管道",
                //    Children = new List<ThumbItemModel>() {
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //}
                //};
                //ThumbList.Add(model);
                #endregion

                #region 控制开关数据
                //model = new ThumbModel()
                //{
                //    Header = "控制开关",
                //    Children = new List<ThumbItemModel>() {
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //}
                //};
                //ThumbList.Add(model);
                #endregion

                #region 其它组件数据
                //model = new ThumbModel()
                //{
                //    Header = "其他组件",
                //    Children = new List<ThumbItemModel>() {
                //    new ThumbItemModel(),
                //    new ThumbItemModel(),
                //    new ThumbItemModel()
                //}
                //};
                //ThumbList.Add(model);
                #endregion
                #endregion

                // 初始化组态组件
                ComponentsInit();

                ItemDropCommand = new RelayCommand<object>(DoItemDropCommand); // 编辑区域组件放下触发的命令
                SaveCommand = new RelayCommand<object>(DoSaveCommand); // 保存按钮命令
                CloseSaveFailedCommand = new RelayCommand<object>(obj =>
                {   // 执行关闭提示信息面板动画
                    VisualStateManager.GoToElementState(obj as Window, "SaveFailedClose", true);
                });

                // 组件选中命令
                DeviceSelectedCommand = new RelayCommand<DeviceItemModel>(model =>
                {
                    // 记录一个当前选中组件
                    // Model = DeviceItemModel
                    // 对当前组件进行选中
                    // 进行属性、点位编辑
                    if (CurrentDevice != null)  // 如果当前选中项不为null则选中取消
                        CurrentDevice.IsSelected = false;
                    if (model != null) // 将当前选中项设置为选中状态
                    {
                        model.IsSelected = true;
                    }

                    CurrentDevice = model;
                });

                KeyDownCommand = new RelayCommand<object>(obj =>
                {
                    if (CurrentDevice != null)
                    {
                        var ea = obj as KeyEventArgs;
                        if (ea.Key == Key.Up)
                            CurrentDevice.Y--;
                        else if (ea.Key == Key.Down)
                            CurrentDevice.Y++;
                        else if (ea.Key == Key.Left)
                            CurrentDevice.X--;
                        else if (ea.Key == Key.Right)
                            CurrentDevice.X++;

                        else if (ea.Key == Key.Escape)
                            CurrentDevice.IsSelected = false;
                    }
                });
                // 实例化页面关闭命令
                CloseCommand = new RelayCommand<object>(obj =>
                {
                    (obj as Window).DialogResult = _windowState;
                });

                // 初始化组件通信属性选项
                var pos = localDataAccess.GetPropertyOption();
                // 将数据库获取的属性列表数据转换成Mode数据
                PropOptions = pos.Select(p =>
                {
                    var pom = new PropOptionModel
                    {
                        Header = p.PropHeader,
                        PropName = p.PropName,
                        PropType = p.PropType
                    };
                    // 修改目的有两个：
                    // 1、初始化当前属性选项所对应的值的选项
                    // 2、希望加载值选项后，初始化一个默认选项
                    var list = InitOptions(p.PropName, out int DefaultIndex);
                    pom.ValueOptions = list;
                    pom.DefaultIndex = DefaultIndex;

                    return pom;
                }
                ).ToList();
            }
        }

        /// <summary>
        /// 初始化编辑区域的组态控件
        /// </summary>
        private void ComponentsInit()
        {
            // 从数据库中查询出组态控件数据添加到组态控件集合中去
            var ds = _localDataAccess.GetDevices().Select(d =>
            {
                var dim = new DeviceItemModel()  // 初始化组件数据
                {
                    Header = d.Header,
                    X = double.Parse(d.X),
                    Y = double.Parse(d.Y),
                    Z = int.Parse(d.Z),
                    Width = double.Parse(d.W),
                    Height = double.Parse(d.H),
                    DeviceType = d.DeviceTypeName,
                    DeviceNum = d.DeviceNum,
                    FlowDirection = int.Parse(d.FlowDirection),
                    Rotate = int.Parse(d.Rotate),

                    PropList = new ObservableCollection<DevicePropModel>(
                            d.Props.Select(dp => new DevicePropModel
                            {
                                PropName = dp.PropName,
                                PropValue = dp.PropValue,
                            })),

                    VariableList = new ObservableCollection<VariableModel>(
                            d.Vars.Select(dv => new VariableModel
                            {
                                VarNum = dv.VarNum,
                                VarName = dv.Header,
                                VarAddress = dv.Address,
                                Offset = dv.Offset,
                                Modulus = dv.Modulus,
                                VarType = dv.VarType,
                            })),
                    //绑定组件删除命令
                    DeleteCommand = new RelayCommand<DeviceItemModel>(model => DeviceList.Remove(model)),
                    Devices = () => DeviceList.ToList() // 初始化委托方式获取组件集合属性
                };
                // 初始化每个组件的右键菜单 
                dim.InitContextMenu();

                return dim;
            });
            // 赋值到动态组件集合中
            DeviceList = new ObservableCollection<DeviceItemModel>(ds);

            // 用于辅助组件-水平对齐线
            DeviceList.Add(new DeviceItemModel { X = 0, Y = 0, Width = 2000, Height = 0.5, Z = 9999, DeviceType = "HL", IsVisible = false });
            // 用于辅助组件-垂直对齐线
            DeviceList.Add(new DeviceItemModel { X = 0, Y = 0, Width = 0.5, Height = 2000, Z = 9999, DeviceType = "VL", IsVisible = false });
            // 用于辅助组件-宽度对齐线
            DeviceList.Add(new DeviceItemModel { X = 0, Y = 0, Width = 0, Height = 15, Z = 9999, DeviceType = "WidthRule", IsVisible = false });
            // 用于辅助组件-高度对齐线
            DeviceList.Add(new DeviceItemModel { X = 0, Y = 0, Width = 15, Height = 0, Z = 9999, DeviceType = "HeightRule", IsVisible = false });
        }

        /// <summary>
        /// 编辑区域组件放下触发的命令方法
        /// </summary>
        /// <param name="obj"></param>
        private void DoItemDropCommand(object obj)
        {
            DragEventArgs e = obj as DragEventArgs;
            // 获取组件数据
            var data = (ThumbItemModel)e.Data.GetData(typeof(ThumbItemModel));
            // 获取拖动到的坐标点
            var point = e.GetPosition((IInputElement)e.Source);

            var dim = new DeviceItemModel
            {
                Header = data.Header, // 赋值标题-用于拖动后显示组件标题
                DeviceNum = DateTime.Now.ToString("yyyyMMddHHmmss"),
                DeviceType = data.TargetType,
                Width = data.Width,
                Height = data.Height,
                X = point.X - data.Width / 2,  // 减去宽度/2是为了要让组件放下去后鼠标在组件的中间位置。
                Y = point.Y - data.Height / 2,
                // 绑定组件的移除命令
                DeleteCommand = new RelayCommand<DeviceItemModel>(model => DeviceList.Remove(model)),
                Devices = () => DeviceList.ToList()
            };
            dim.InitContextMenu(); // 初始化右键菜单
            // 添加动态组件
            DeviceList.Add(dim);
        }

        /// <summary>
        /// 保存按钮方法
        /// </summary>
        /// <param name="obj"></param>
        private void DoSaveCommand(object obj)
        {
            #region 初始化提示信息面板动画效果
            VisualStateManager.GoToElementState(obj as Window, "NormalSuccess", true);
            VisualStateManager.GoToElementState(obj as Window, "SaveFailedNormal", true);
            #endregion

            // 获取编辑区除辅助线以外的组件集合
            var ds = DeviceList
                .Where(d => !new string[] { "HL", "VL", "WidthRule", "HeightRule" }.Contains(d.DeviceType))
                .Select(dev => new DeviceEntity
                {
                    DeviceNum = dev.DeviceNum,
                    X = dev.X.ToString(),
                    Y = dev.Y.ToString(),
                    Z = dev.Z.ToString(),
                    W = dev.Width.ToString(),
                    H = dev.Height.ToString(),
                    DeviceTypeName = dev.DeviceType,

                    FlowDirection = dev.FlowDirection.ToString(),
                    Rotate = dev.Rotate.ToString(),

                    // 转换属性集合 - 串口、tcp等连接数据
                    Props = dev.PropList.Select(dp => new DevicePropItemEntity
                    {
                        PropName = dp.PropName,
                        PropValue = dp.PropValue,
                    }).ToList(),

                    // 转换点位集合 - Modbus的配置数据
                    Vars = dev.VariableList.Select(dv => new VariableEntity
                    {
                        VarNum = dv.VarNum,
                        Header = dv.VarName,
                        Address = dv.VarAddress,
                        Offset = dv.Offset,
                        Modulus = dv.Modulus,
                        VarType = dv.VarType
                    }).ToList()
                });
            // 保存组件信息到数据库中
            try
            {
                //throw new Exception("保存异常测试，没有执行实际保存逻辑，只用作查看异常提示效果！");

                _localDataAccess.SaveDevice(ds.ToList());

                _windowState = true;
                // 提示保存成功 - 控制提示面板动画显示
                VisualStateManager.GoToElementState(obj as Window, "SaveSuccess", true);
            }
            catch (Exception ex)
            {
                SaveFailedMessage = ex.Message; // 失败的异常信息
                // 提示保存失败，包括异常信息 - 控制提示面板动画显示
                VisualStateManager.GoToElementState(obj as Window, "SaveFailedShow", true);
            }
        }

        /// <summary>
        /// 获取属性列表实际值下拉列表集合
        /// </summary>
        /// <param name="propName">用于判断的属性名称</param>
        /// <param name="OptionsDefaultIndex">设置默认索引</param>
        /// <returns>下拉列表集合</returns>
        private List<string> InitOptions(string propName, out int OptionsDefaultIndex)
        {
            List<string> values = new List<string>();
            OptionsDefaultIndex = 0;
            switch (propName)
            {
                case "Protocol":  // Modbus通讯
                    values.Add("ModbusRTU");
                    values.Add("ModbusASCII");
                    values.Add("ModbusTCP");
                    values.Add("S7COMM");
                    values.Add("FINSTCP");
                    values.Add("MC3E");
                    break;
                case "PortName": // 串口通讯获取串口名称
                    values = new List<string>(SerialPort.GetPortNames());
                    break;
                case "BaudRate": // 串口通讯 波特率
                    values.Add("2400");
                    values.Add("4800");
                    values.Add("9600");
                    values.Add("19200");
                    values.Add("38400");
                    values.Add("57600");
                    values.Add("115200");

                    OptionsDefaultIndex = 2;
                    break;
                case "DataBit": // 串口通讯 数据位
                    values.Add("5");
                    values.Add("7");
                    values.Add("8");

                    OptionsDefaultIndex = 2;
                    break;
                case "Parity": // 串口通讯 奇 偶校验位
                    values = new List<string>(Enum.GetNames<Parity>());
                    break;
                case "StopBit": // 串口通讯 停止位
                    values = new List<string>(Enum.GetNames<StopBits>());

                    OptionsDefaultIndex = 1;
                    break;
                case "Endian": // 字节序-用于调节数据大小端的
                    values = new List<string>(Enum.GetNames<EndianType>());
                    break;
                default: break;
            }

            return values;
        }
    }
}
